package com.weilx959.spt.core.utils;

import lombok.RequiredArgsConstructor;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * try-catch封装
 *
 * @author weilx
 * @since 2024-04-30
 */
public interface Try<T> {

    /**
     * 创建 {@link Try}<{@link T}>
     *
     * @param supplier 执行函数
     * @return {@link Try}<{@link T}>
     */
    static <T> Try<T> of(Supplier<T> supplier) {
        try {
            return new Success<>(supplier.get());
        } catch (Exception e) {
            return new Failure<>(e);
        }
    }

    /**
     * 创建 {@link Try}<{@link T}>
     *
     * @param runnable 执行函数
     * @return {@link Try}<{@link T}>
     */
    static <T> Try<T> of(Runnable runnable) {
        try {
            runnable.run();
            return new Success<>(null);
        } catch (Exception e) {
            return new Failure<>(e);
        }
    }

    /**
     * 判断是否成功
     *
     * @return boolean
     */
    boolean isSuccess();

    /**
     * 判断是否失败
     *
     * @return boolean
     */
    default boolean isFailure() {
        return !isSuccess();
    }

    /**
     * 成功执行
     *
     * @param consumer 消费者
     * @return {@link Try}<{@link T}>
     */
    default Try<T> success(Consumer<? super T> consumer) {
        if (isSuccess()) {
            consumer.accept(get());
        }
        return this;
    }

    /**
     * 失败执行
     *
     * @param consumer 消费者
     * @return {@link Try}<{@link T}>
     */
    default Try<T> failure(Consumer<? super Throwable> consumer) {
        if (isFailure()) {
            consumer.accept(getCause());
        }
        return this;
    }

    /**
     * 最终执行
     * @param runnable  finally
     */
    default void finalized(Runnable runnable) {
        try {
            runnable.run();
        } catch (Exception e) {
            // ignore
        }
    }

    /**
     * 获取异常
     *
     * @return {@link Throwable}
     */
    default Throwable getCause() {
        throw new UnsupportedOperationException();
    }

    /**
     * 获取值
     *
     * @return {@link T}
     */
    default T get() {
        throw new UnsupportedOperationException();
    }

    /**
     * 成功返回值，失败返回默认值
     *
     * @param other 默认值
     * @return {@link T}
     */
    default T orElse(T other) {
        return isSuccess() ? get() : other;
    }

    /**
     * 成功返回值，失败返回默认值
     *
     * @param supplier 默认值提供者
     * @return {@link T}
     */
    default T orElseGet(Supplier<? extends T> supplier) {
        return isSuccess() ? get() : supplier.get();
    }

    /**
     * 转换
     *
     * @param mapper 转换函数
     * @return {@link Try}<{@link R}>
     */
    default <R> Try<R> map(Function<? super T,? extends R> mapper) {
        if (isSuccess()) {
            try {
                return new Success<>(mapper.apply(get()));
            } catch (Exception e) {
                return new Failure<>(e);
            }
        }
        return (Failure<R>) this;
    }

    default Try<T> then(Runnable runnable) {
        if (isSuccess()) {
            runnable.run();
        }
        return this;
    }

    default Try<T> then(Consumer<? super T> consumer) {
        if (isSuccess()) {
            consumer.accept(get());
        }
        return this;
    }

    /**
     * 成功
     *
     * @author weilx
     * @since 2024-04-30
     */
    @RequiredArgsConstructor
    class Success<T> implements Try<T> {
        private final T value;

        @Override
        public boolean isSuccess() {
            return true;
        }

        @Override
        public T get() {
            return this.value;
        }
    }

    /**
     * 失败
     *
     * @author weilx
     * @since 2024-04-30
     */
    @RequiredArgsConstructor
    class Failure<T> implements Try<T> {
        private final Throwable throwable;

        @Override
        public boolean isSuccess() {
            return false;
        }

        @Override
        public Throwable getCause() {
            return this.throwable;
        }
    }
}
